

#ifndef	_LINKED_QUEUE_2_H_
#define	_LINKED_QUEUE_2_H_

#include "LinkedList2Node.hpp"

template <typename T> class LinkedQueue2{
protected:
	LinkedList2Node<T> *head, *end;
public:
	CALLCONV LinkedQueue2(LinkedList2Node<T> *firstNode = (LinkedList2Node<T>*)0){
		head = end = firstNode;
	}
	
	CALLCONV LinkedQueue2(T firstElement){
		head = end = new LinkedList2Node<T>(firstElement);
	}
	
	inline bool isEmpty(){
		if(this == (LinkedQueue2*)0) return true;
		if(head == (LinkedList2Node<T>*)0) return true;
		return false;
	}
	
	CALLCONV unsigned getSize(){
		if(this == (LinkedQueue2*)0) return 0;
		unsigned size = 0;
		for(LinkedList2Node<T> *temp = head;
			temp != (LinkedList2Node<T>*)0;
			temp = temp->next) size++;
		return size;
	}
	
	CALLCONV unsigned indexOf(T element){
		if(this == (LinkedQueue2*)0) return ~(unsigned)0;
		unsigned index = 0;
		for(LinkedList2Node<T> *temp = head;
				temp != (LinkedList2Node<T>*)0;
				temp = temp->next, index++)
			if(temp->key == element) return index;
		return ~(unsigned)0;
	}
	
	CALLCONV bool addElementToFirst(T element){
		if(this == (LinkedQueue2*)0) return false;
		head = new LinkedList2Node<T>(element, head);
		if(head->next != (LinkedList2Node<T>*)0) head->next->prev = head;
		if(end == (LinkedList2Node<T>*)0) end = head;
		return true;
	}
	
	CALLCONV bool addElementToLast(T element){
		if(this == (LinkedQueue2*)0) return false;
		end = new LinkedList2Node<T>(element,
			(LinkedList2Node<T>*)0, end);
		if(end->prev != (LinkedList2Node<T>*)0) end->prev->next = end;
		if(head == (LinkedList2Node<T>*)0) head = end;
		return true;
	}
	
	CALLCONV bool setFirstElement(T element){
		if(this == (LinkedQueue2*)0) return false;
		if(head == (LinkedList2Node<T>*)0) return false;
		head->key = element;
		return true;
	}
	
	CALLCONV bool setLastElement(T element){
		if(this == (LinkedQueue2*)0) return false;
		if(end == (LinkedList2Node<T>*)0) return false;
		end->key = element;
		return true;
	}
	
	CALLCONV bool getFirstElement(T *pe){
		if(this == (LinkedQueue2*)0) return false;
		if(head == (LinkedList2Node<T>*)0) return false;
		if(pe == (T*)0) return false;
		*pe = head->key;
		return true;
	}
	
	CALLCONV bool getLastElement(T *pe){
		if(this == (LinkedQueue2*)0) return false;
		if(end == (LinkedList2Node<T>*)0) return false;
		if(pe == (T*)0) return false;
		*pe = end->key;
		return true;
	}
	
	CALLCONV bool removeFirstElement(T *pe){
		if(this == (LinkedQueue2*)0) return false;
		if(head == (LinkedList2Node<T>*)0) return false;
		if(pe != (T*)0) *pe = head->key;
		LinkedList2Node<T> *temp = head;
		if((head = head->next) == (LinkedList2Node<T>*)0)
			end = (LinkedList2Node<T>*)0;
		else head->prev = (LinkedList2Node<T>*)0;
		delete temp;
		return true;
	}
	
	CALLCONV bool removeLastElement(T *pe){
		if(this == (LinkedQueue2*)0) return false;
		if(head == (LinkedList2Node<T>*)0) return false;
		if(pe != (T*)0) *pe = end->key;
		LinkedList2Node<T> *temp = end;
		if((end = end->prev) == (LinkedList2Node<T>*)0)
			head = (LinkedList2Node<T>*)0;
		else end->next = (LinkedList2Node<T>*)0;
		delete temp;
		return true;
	}
	
	
}; // class LinkedQueue2<T>

#endif	// _LINKED_QUEUE_2_H_
